﻿using System;
using System.Linq;
using Microsoft.Practices.ObjectBuilder2;
using Microsoft.Practices.Unity;
using TestByWire.Factories;

namespace TestByWire.BuildStrategies
{
	internal class AutoInjectionBuildStrategy : BuilderStrategy
	{
		private readonly IUnityContainer _container;
		private readonly IStubInstanceFactory _stubInstanceFactory;

		public AutoInjectionBuildStrategy(
			IUnityContainer container,
			IStubInstanceFactory stubInstanceFactory,
			Type typeUnderTest)
		{
			if (container == null)
			{
				throw new ArgumentNullException("container");
			}

			if (stubInstanceFactory == null)
			{
				throw new ArgumentNullException("stubInstanceFactory");
			}

			if (typeUnderTest == null)
			{
				throw new ArgumentNullException("typeUnderTest");
			}

			_container = container;
			_stubInstanceFactory = stubInstanceFactory;
		}

		public override void PreBuildUp(IBuilderContext context)
		{
			var pipelineSettings = _container.Resolve<PipelineSettings>();
			var nextStub = new DoNotStub(context.OriginalBuildKey.Type, context.OriginalBuildKey.Name);
			if (!context.BuildComplete &&
				!pipelineSettings.DoNotStubList.Contains(nextStub) &&
				!nextStub.IsInContainer(_container))
			{
				StubCreationResult creationResult = _stubInstanceFactory.CreateStubInstanceOf(context.OriginalBuildKey.Type, context.OriginalBuildKey.Name);
				context.Existing = creationResult.Instance;

				if (creationResult.CompletesBuild)
				{
					context.BuildComplete = true;
				}
			}
		}
	}
}